package com.liuzhilong.util.easyimport.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liuzhilong.util.easyimport.annotation.TargetColumn;
import com.liuzhilong.util.easyimport.annotation.TargetSheet;
import com.liuzhilong.util.easyimport.exception.NoSheetException;
import com.liuzhilong.util.easyimport.exception.NotSupportFileTypeException;

public class ExcelMappingFactory {
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
	
	private  Workbook workbook;
	
	private FileInputStream fileInputStream;
	
	private ExcelMappingFactory() {
		
	}
	private ExcelMappingFactory(Workbook workbook ) {
		this.workbook = workbook;
	}
	
	
	private ExcelMappingFactory(File workFile) throws IOException,FileNotFoundException  {
		
		if(workFile.getName().toUpperCase().endsWith("XLS")) {
			fileInputStream = new FileInputStream(workFile);
			workbook = new HSSFWorkbook(fileInputStream);
		}else if(workFile.getName().toUpperCase().endsWith("XLSX")) {
			fileInputStream = new FileInputStream(workFile);
			workbook = new XSSFWorkbook(fileInputStream);
		}else {
			throw new NotSupportFileTypeException("不支持的文件格斯");
		}
		
	} 
	
	
	
	private ExcelMappingFactory(FileInputStream workFileSteam,String fileTpye) throws IOException,FileNotFoundException {
		
		if(fileTpye.toUpperCase().endsWith("XLS")) {
			this.fileInputStream = workFileSteam;
			workbook = new HSSFWorkbook(workFileSteam);
		}else if(fileTpye.toUpperCase().endsWith("XLSX")) {
			this.fileInputStream = workFileSteam;
			workbook = new XSSFWorkbook(workFileSteam);
		}else {
			if(logger.isInfoEnabled()) {
				logger.info("不支持的文件格斯"+fileTpye);
			}
			throw new NotSupportFileTypeException("不支持的文件格斯");
		}
		
	} 
	
	
	public static ExcelMappingFactory createFactory(Workbook workbook )   throws IOException,FileNotFoundException{
		return new ExcelMappingFactory(workbook);
	}
	public static ExcelMappingFactory createFactory(File workFile )  throws IOException,FileNotFoundException {
		return new ExcelMappingFactory(workFile);
	}
	public static ExcelMappingFactory createFactory(FileInputStream workFileSteam,String fileTpye )  throws IOException,FileNotFoundException{
		return new ExcelMappingFactory( workFileSteam, fileTpye );
	}
	
	
	
	
	
	
	/**
	 * 获取BEAN的mapping对象
	 * @param mappingbean
	 * @return
	 */
	public ExcelMapping  createMapping(  Class<?> mappingbean  ) {
		checkClassSupport(mappingbean);
		
		/*
		 * 通过注解类的名称获取对应的sheet名称 
		 * 如果没有名称 则默认class的名字
		 * 如果wk中没有对应的名字  直接处处异常
		 * 
		 */
		String className=mappingbean.getSimpleName();
		TargetSheet sheet = mappingbean.getAnnotation(TargetSheet.class);
		String sheetName = sheet.name().equals("")?className:sheet.name();
		if(this.workbook.getSheetIndex(sheetName)==-1) {
			if(logger.isInfoEnabled()) {
				logger.info("没有名字为"+sheetName+"的sheet名称");
			}
			throw new NoSheetException("没有名字为"+sheetName+"的sheet名称").setSheetName(sheetName);
		}
		
		
		
		
		return new ExcelMappingInner(workbook.getSheet(sheetName),mappingbean);
	}
	/**
	 * 校验类是否是用注解来弄的
	 * @param mappingbean
	 */
	private  void checkClassSupport( Class<?> mappingbean) {
		//无注解
		if(!mappingbean.isAnnotationPresent(TargetSheet.class)) {
			throw new RuntimeException("没有注解");
		}
		//匿名类
		String className=mappingbean.getSimpleName();
		if(className.equals("")) {
			throw new RuntimeException("不支持匿名类");
		}
		//mapingrow的行数必须小于读取列的夯实
		TargetSheet targetSheet = mappingbean.getAnnotation(TargetSheet.class);
		if(targetSheet.mappingRow()>=targetSheet.dataStartRow()) {
			throw new RuntimeException("mapingrow的行数必须小于读取列的行数");
		}
		
		//是否注解列
		Field[] fields = mappingbean.getDeclaredFields();
		int anoCount = 0;
		for(Field item:fields) {
			if(item.isAnnotationPresent(TargetColumn.class)) {
				anoCount++;
				break;
			}
		}
		if(anoCount == 0) {
			throw new RuntimeException("javabean没有指定映射规则");
		}
		
	}
	
	public void destroy() {
		if(this.fileInputStream!=null) {
			try {
				fileInputStream.close();
				logger.info("destory success");
			} catch (IOException e) {
				logger.info("destory fail"+e.getCause().getMessage());
			}
		}
	}
}
